import {Injectable} from '@angular/core';
import {Farm} from '../entity/farm.model';
import {Menu} from '../entity/menu.model';
import {User} from '../entity/user.model';
import {ParamDict, MenuParamDict} from '../entity/menu-param-dict.model';
import {Company} from '../entity/company.model';
import {UserProfile} from '../entity/user-profile.model';
import {TagDict} from '../entity/tag-dict.model';
import {SetofkeyDict, SetofvalueDict} from '../entity/setof-dict.model';
import {TagDictService} from './tag-dict.service';
import {SetofDictService} from './setof-dict.service';
import {MenuParamDictService} from './menu-param-dict.service';
import {HttpClient} from '@angular/common/http';
import {Observable, Subject} from 'rxjs/Rx';
import {AppConfig} from '../config';
import {environment} from '../../environments/environment'

@Injectable()
export class ApplicationService {
  private _sessionStorage: Storage;
  private _localStorage: Storage;
  private _location: Location;
  private _currentUserFarms: Farm[];
  private _currentMenuParams: ParamDict;
  private _menuParams: MenuParamDict;
  private _tagDict: TagDict;
  private _setKey: SetofkeyDict;
  private _setValue: SetofvalueDict;
  private _appConfigData: AppConfigData;
  public currentMenuParamsSubject: Subject<ParamDict> = new Subject<ParamDict>();
  public _currentApplicationParams: ParamDict;

  /**
   * 数据参数是否初始化完成
   *
   * @readonly
   * @type {User}
   * @memberof ApplicationService
   */
  public get initApplicationCompleted(): boolean {
    return this.sessionStorageGetItem<boolean>('initApplicationCompleted');
  }

  public set initApplicationCompleted(value: boolean) {
    this.sessionStorageSetItem('initApplicationCompleted', value);
  }

  /**
   * 应用程序配置是否初始化完成
   *
   * @readonly
   * @type {User}
   * @memberof ApplicationService
   */
  public get initAppConfigDataCompleted(): boolean {
    return this.sessionStorageGetItem<boolean>('initAppConfigDataCompleted');
  }

  public set initAppConfigDataCompleted(value: boolean) {
    this.sessionStorageSetItem('initAppConfigDataCompleted', value);
  }

  /**
   * 获得当前网站基地址
   *
   * @type {Location}
   * @memberof ApplicationService
   */
  public get baseHref(): string {
    return this._location.href;
  }

  /**
   * 获得window.location对象
   *
   * @type {Location}
   * @memberof ApplicationService
   */
  public get location(): Location {
    return this._location;
  }

  /**
   * 获取或设置当前用户
   *
   * @readonly
   * @type {User}
   * @memberof ApplicationService
   */
  public get currentUser(): User {
    return this.sessionStorageGetItem<User>('currentUser');
  }

  public set currentUser(value: User) {
    this.sessionStorageSetItem('currentUser', value);
  }

  public get callbackURL(): string {
    return this.sessionStorageGetItem<string>('callbackURL');
  }

  public set callbackURL(value: string) {
    this.sessionStorageSetItem('callbackURL', value);
  }


  /**
   * 获取或设置当前用户
   *
   * @readonly
   * @type {UserProfile}
   * @memberof ApplicationService
   */
  public get currentUserProfile(): UserProfile {
    return this.sessionStorageGetItem<UserProfile>('currentUserProfile');
  }

  public set currentUserProfile(value: UserProfile) {
    this.sessionStorageSetItem('currentUserProfile', value);
  }

  /**
   * 获取或设置当前用户所属公司
   *
   * @readonly
   * @type {Company}
   * @memberof ApplicationService
   */
  public get currentCompany(): Company {
    return this.sessionStorageGetItem<Company>('currentCompany');
  }

  public set currentCompany(value: Company) {
    this.sessionStorageSetItem('currentCompany', value);
  }

  /**
   * 获取或设置当前用户拥有的风场权限
   *
   * @readonly
   * @type {Farm[]}
   * @memberof ApplicationService
   */
  public get currentUserFarms(): Farm[] {
    if (!this._currentUserFarms) {
      this._currentUserFarms = this.sessionStorageGetItem<Farm[]>('currentUserFarms');
    }
    return this._currentUserFarms;
  }

  public set currentUserFarms(value: Farm[]) {
    this.sessionStorageSetItem('currentUserFarms', value);
    this._currentUserFarms = value;
  }

  /**
   * 获取或设置当前菜单
   *
   * @type {Menu}
   * @memberof ApplicationService
   */
  public get currentMenu(): Menu {
    return this.sessionStorageGetItem<Menu>('currentMenu');
  }

  /**
   * 设置当前菜单
   * 同时根据菜单ID查询菜单参数集合完成菜单参数写入
   * @memberof ApplicationService
   */
  public set currentMenu(value: Menu) {
    this.sessionStorageSetItem('currentMenu', value);
    try {
      let menuParams = this.menuParams[value.menuId];
      if (menuParams) {

        this.currentMenuParams = menuParams;
        this.currentMenuParamsSubject.next(this.currentMenuParams);
      }
      else {
        this.currentMenuParams = null;
        this.currentMenuParamsSubject.next(this.currentMenuParams);
      }
    }
    catch (err) {
      throw err;
    }
  }

  /**
   * 获取当前菜单参数
   *
   * @type {ParamDict}
   * @memberof ApplicationService
   */
  public get currentMenuParams(): ParamDict {
    if (!this._currentMenuParams) {
      this._currentMenuParams = this.sessionStorageGetItem<ParamDict>('currentMenuParams');
    }
    return this._currentMenuParams;
  }

  public set currentMenuParams(value: ParamDict) {
    this.sessionStorageSetItem('currentMenuParams', value);
    this._currentMenuParams = value;
  }

  /**
   * 获取系统菜单参数
   *
   * @type {ParamDict}
   * @memberof ApplicationService
   */
  public get currentApplicationParams(): ParamDict {
    if (!this._currentApplicationParams) {
      this._currentApplicationParams = this.sessionStorageGetItem<ParamDict>('currentApplicationParams');
    }
    return this._currentApplicationParams;
  }

  public set currentApplicationParams(value: ParamDict) {
    this.sessionStorageSetItem('currentApplicationParams', value);
    this._currentApplicationParams = value;
  }

  /**
   * 获取当前菜单参数
   *
   * @type {ParamDict}
   * @memberof ApplicationService
   */
  public get menuParams(): MenuParamDict {
    if (!this._menuParams) {
      this._menuParams = this.sessionStorageGetItem<MenuParamDict>('menuParams');
    }
    return this._menuParams;
  }

  public set menuParams(value: MenuParamDict) {
    this.sessionStorageSetItem('menuParams', value);
    this._menuParams = value;
  }


  /**
   * 获取或设置tag字典
   *
   * @type {TagDict}
   * @memberof ApplicationService
   */
  public get tagDict(): TagDict {
    if (!this._tagDict) {
      this._tagDict = this.sessionStorageGetItem<TagDict>('tagDict');
    }
    return this._tagDict
  }

  public set tagDict(value: TagDict) {
    this.sessionStorageSetItem('tagDict', value);
    this._tagDict = value;
  }

  /**
   * 获取或设置SetofkeyDict字典
   *
   * @type {TagDict}
   * @memberof ApplicationService
   */
  public get setKeyDict(): SetofkeyDict {
    if (!this._setKey) {
      this._setKey = this.sessionStorageGetItem<SetofkeyDict>('setKey');
    }
    return this._setKey;
  }

  public set setKeyDict(value: SetofkeyDict) {
    this.sessionStorageSetItem('setKey', value);
    this._setKey = value;
  }


  /**
   * 获取或设置SetofvalueDict字典
   *
   * @type {TagDict}
   * @memberof ApplicationService
   */
  public get setValueDict(): SetofvalueDict {
    if (!this._setValue) {
      this._setValue = this.sessionStorageGetItem<SetofvalueDict>('setValue');
    }
    return this._setValue;
  }

  public set setValueDict(value: SetofvalueDict) {
    this.sessionStorageSetItem('setValue', value);
    this._setValue = value;
  }


  /**
   * 获取或设置登录数据
   *
   * @type {LoginData}
   * @memberof ApplicationService
   */
  public get loginData(): LoginData {
    return this.localStorageGetItem<LoginData>('loginData');
  }

  public set loginData(value: LoginData) {
    this.localStorageSetItem('loginData', value);
  }

  /**
   * 获取或设置用户token
   *
   * @type {LoginData}
   * @memberof ApplicationService
   */
  public get userToken(): string {
    return this.localStorageGetItem<string>('userToken');
  }

  public set userToken(value: string) {
    this.localStorageSetItem('userToken', value);
  }

  /**
   * 获取或设置 App 配置信息
   *
   * @type {AppConfig}
   * @memberof ApplicationService
   */
  public get appConfigData(): AppConfigData {
    if (!this._appConfigData) {
      this._appConfigData = this.sessionStorageGetItem<AppConfigData>('appConfigData');
      if (this._appConfigData) {
        AppConfig.APP_TITLE = this._appConfigData.appTitle;
        AppConfig.APP_SUBTITLE = this._appConfigData.appSubTitle;
        AppConfig.APP_NAME = this._appConfigData.appName;
        AppConfig.APP_SUBNAME = this._appConfigData.appSubName;
        AppConfig.APP_LOG = this._appConfigData.appLog;
        AppConfig.APP_FAVICON = this._appConfigData.appFavicon;
        AppConfig.APP_RESTFUL = this._appConfigData.appRestful;
        AppConfig.APP_WEBSOCKET = this._appConfigData.appWebSocket;
        AppConfig.APP_RANDOM = this._appConfigData.appRandom;
        AppConfig.APP_COMPANY = this._appConfigData.appCompany;
        AppConfig.APP_REPORT = this.appConfigData.appReport;
        AppConfig.APP_3D = this.appConfigData.app3D;
        AppConfig.APP_STATION = this.appConfigData.appStation;
        AppConfig.APP_ISSHOWERR = this.appConfigData.isShowErr;
      }
    }
    return this._appConfigData;
  }

  public set appConfigData(value: AppConfigData) {
    // this.sessionStorageSetItem('appConfigData', value);
    this._appConfigData = value;
  }


  /**
   * Creates an instance of ApplicationService.
   * @param {MenuParamDictService} menuParamDictService
   * @param {SetofDictService} setofDictService
   * @param {TagDictService} tagDictService
   * @memberof ApplicationService
   */
  constructor(
    private http: HttpClient,
    private menuParamDictService: MenuParamDictService,
    private setofDictService: SetofDictService,
    private tagDictService: TagDictService,
  ) {
    if (!window.sessionStorage)
      throw new Error('当前浏览器不支持 window.sessionStorage ！');
    if (!window.localStorage)
      throw new Error('当前浏览器不支持 window.localStorage ！');
    this._localStorage = window.sessionStorage; // 因为 opgview 登录会清理storage，所以都存储到session 中
    this._sessionStorage = window.sessionStorage;
    this._location = window.location;

    let self = this;
    //监听窗口关闭或刷新事件
    window.onbeforeunload = function () {
      self.currentMenuParamsSubject.unsubscribe();
    }
  }


  /**
   * 初始化应用配置文件
   *
   * @returns {Observable<Result>}
   * @memberof ApplicationService
   */
  public initAppConfigData(): Observable<Result> {
    let configUrl = '';
    if (environment.production) {
      configUrl = `assets/config/config.json?time=${(new Date()).getTime()}`;
    } else {
      configUrl = `assets/config/config_dev.json?time=${(new Date()).getTime()}`;
    }
    return Observable.create(observer => {
      this.http.get(configUrl).subscribe(
        next => {
          try {
            let host: string = window.location.host
            this.appConfigData = next as any;
            if (host.indexOf(':4200') == -1) {
              this.appConfigData.appRestful = 'http://' + host + '/webapi/v1'
              this.appConfigData.appWebSocket = 'ws://' + host + '/webapi'
            }
            AppConfig.APP_TITLE = this.appConfigData.appTitle;
            AppConfig.APP_SUBTITLE = this.appConfigData.appSubTitle;
            AppConfig.APP_NAME = this.appConfigData.appName;
            AppConfig.APP_SUBNAME = this.appConfigData.appSubName;
            AppConfig.APP_LOG = this.appConfigData.appLog;
            AppConfig.APP_FAVICON = this.appConfigData.appFavicon;
            AppConfig.APP_RESTFUL = this.appConfigData.appRestful;
            AppConfig.APP_WEBSOCKET = this.appConfigData.appWebSocket;
            AppConfig.APP_RANDOM = this.appConfigData.appRandom;
            AppConfig.APP_COMPANY = this.appConfigData.appCompany;
            AppConfig.APP_REPORT = this.appConfigData.appReport;
            AppConfig.APP_3D = this.appConfigData.app3D;
            AppConfig.APP_STATION = this.appConfigData.appStation;
            AppConfig.APP_ISSHOWERR = this.appConfigData.isShowErr;
            // this.initAppConfigDataCompleted = true;
            let result: Result = {
              success: true,
              message: '初始化配置文件成功。'
            }
            observer.next(result);
          }
          catch (error) {
            observer.error(error);
          }
        },
        error => {
          observer.error(error);
        });
    });
  }


  /**
   * 初始化应用程序参数
   *
   * @param {User} currentUser
   * @param {UserProfile} currentUserProfile
   * @param {Company} currentCompany
   * @param {Farm[]} currentUserFarms
   * @memberof ApplicationService
   */
  public initApplicationData(
    currentUser: User,
    currentUserProfile: UserProfile,
    currentCompany: Company,
    currentUserFarms: Farm[],
    // callbackURL:string
  ): Observable<Result> {
    return Observable.create(observer => {

      this.currentUser = currentUser;
      this.currentUserProfile = currentUserProfile;
      this.currentCompany = currentCompany;
      this.currentUserFarms = currentUserFarms;
      let menuParam = this.menuParamDictService.initData();
      let setofDict = this.setofDictService.initData();
      let tagDict = this.tagDictService.initData();
      Promise.all([menuParam, setofDict, tagDict])
        .then(res => {
          try {
            this.menuParams = this.menuParamDictService.menuParamDict;
            this.tagDict = this.tagDictService.getTag;
            this.setKeyDict = this.setofDictService.getSetofValues;
            this.setValueDict = this.setofDictService.getSetofValue;
            this.initApplicationCompleted = true;
            this.currentApplicationParams = this.menuParamDictService.menuParamDict['0'];
            // this.callbackURL = window.location.href.split("callbackURL=")[1];
            observer.next({
              success: true,
              message: '初始化配置文件成功。'
            });
          }
          catch (error) {
            this.initApplicationCompleted = false;
            observer.error(error);
          }
        })
        .catch(err => {
          this.initApplicationCompleted = false;
          observer.error(err);
        })
    });

  }

  /**
   * 获得浏览器sessionStorage获得存储值并且转换为相应的对象
   *
   * @private
   * @template T
   * @param {string} key
   * @returns {T}
   * @memberof ApplicationService
   */
  public sessionStorageGetItem<T>(key: string): T {
    try {
      let json = this._sessionStorage.getItem(key);
      if (json && json != '') {
        return JSON.parse(json);
      }
      return null;
    }
    catch (err) {
      throw err;
    }
  }

  /**
   * 往浏览器 sessionStorage 对象写入值
   * 如果值为空增移除对象
   * @private
   * @param {string} key
   * @param {*} value
   * @memberof ApplicationService
   */
  public sessionStorageSetItem(key: string, value: any) {
    try {
      if (value != null) {
        this._sessionStorage.setItem(key, JSON.stringify(value));
      }
      else {
        this._sessionStorage.removeItem(key);
      }
    }
    catch (err) {
      throw err;
    }
  }

  /**
   * 获得浏览器 localStorage 获得存储值并且转换为相应的对象
   *
   * @private
   * @template T
   * @param {string} key
   * @returns {T}
   * @memberof ApplicationService
   */
  public localStorageGetItem<T>(key: string): T {
    try {
      let json = this._localStorage.getItem(key);
      if (json && json != '') {
        return JSON.parse(json);
      }
      return null;
    }
    catch (err) {
      throw err;
    }
  }

  /**
   * 往浏览器 localStorage 对象写入值
   * 如果值为空增移除对象
   * @private
   * @param {string} key
   * @param {*} value
   * @memberof ApplicationService
   */
  public localStorageSetItem(key: string, value: any) {
    try {
      if (value != null) {
        this._localStorage.setItem(key, JSON.stringify(value));
      }
      else {
        this._localStorage.removeItem(key);
      }

    }
    catch (err) {
      throw err;
    }
  }


  /**
   * 清空
   *
   * @memberof ApplicationService
   */
  public clear() {
    let loginData: LoginData = this.loginData;
    loginData.auto = false;
    loginData.password = '';
    this.loginData = loginData;
    this._sessionStorage.clear();
    this.initAppConfigDataCompleted = false;
    this.initApplicationCompleted = false;
  }


}

export interface LoginData {
  userName: string;
  password: string;
  auto: boolean;
  loginState: boolean;
}

export interface AppConfigData {
  /**
   * APP 名称
   *
   * @static
   * @type {string}
   * @memberof AppConfig
   */
  appName: string;
  /**
   * APP 子名称
   *
   * @static
   * @type {string}
   * @memberof AppConfig
   */
  appSubName: string;
  /**
   * APP 描述信息
   *
   * @type {string}
   * @memberof AppConfig
   */
  appDescription: string;
  /**
   * APP log
   *
   *  @type {string}
   * @memberof AppConfig
   */
  appLog: string;
  /**
   * APP 小图标
   *
   * @type {string}
   * @memberof AppConfig
   */
  appFavicon: string;
  /**
   * APP 标题
   *
   * @memberof AppConfig
   */
  appTitle: string;
  /**
   * APP 子标题
   *
   * @type {string}
   * @memberof AppConfig
   */
  appSubTitle: string;
  /**
   * APP http请求的基地址
   *
   * @type {string}
   * @memberof AppConfig
   */
  appRestful: string;
  /**
   * APP websocket请求的基地址
   *
   * @type {string}
   * @memberof AppConfig
   */
  appWebSocket: string;
  /**
   * 调用 websocket是开启随机数
   * true:开启随机数
   * false:不开启随机数
   * @static
   * @type {boolean}
   * @memberof AppConfig
   */
  appRandom: boolean;

  /**
   * APP 公司省份地图配置项（广东：gd）
   * @static
   * @type {string}
   * @memberof AppConfig
   */
  appCompany: string;
  /**
   * APP 报表基地址
   *
   * @type {string}
   * @memberof AppConfigData
   */
  appReport: string;
  /**
   * 3d地址 (发布的时候该地址)
   *
   * @static
   * @type {string}
   * @memberof AppConfig
   */
  app3D: string;
  /**
   * 升压站地址 (发布的时候该地址)
   *
   * @static
   * @type {string}
   * @memberof AppConfig
   */
  appStation: string;

  /**
   * 是否心事错误信息
   *
   * @static
   * @type {string}
   * @memberof AppConfig
   */
  isShowErr: boolean;
}

export interface Result {
  /**
   * 是否成功
   *
   * @type {boolean}
   * @memberof Result
   */
  success: boolean;
  /**
   * 数据对象
   *
   * @type {boolean}
   * @memberof Result
   */
  data?: any;
  /**
   * 消息
   *
   * @type {boolean}
   * @memberof Result
   */
  message?: string;
  /**
   * 错误信息
   *
   * @type {boolean}
   * @memberof Result
   */
  error?: Error;
}
